<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2018/11/27
 * Time: 8:29
 */

namespace app\storage\service;


use api\storage\common\Constant;
use api\storage\service\output\ForeignOutputService;
use api\storage\service\output\LocalOutputService;
use api\storage\service\SocketService;
use app\storage\common\AppConstant;
use app\storage\common\Template;
use app\storage\model\BomDetailModel;
use app\storage\model\BomModel;
use app\storage\model\FileModel;
use app\storage\model\SeatModel;
use app\storage\model\UserModel;
use service\excel\ExcelReaderFactory;
use service\k3\K3ReaderFactory;
use think\Db;
use service\file\CommonFile;

class BomService
{
    private $bomModel;
    private $bomDetailModel;

    public function __construct()
    {
        $this->bomModel = new BomModel();
        $this->bomDetailModel = new BomDetailModel();
    }

    /**
     * 将出库单号中的单号与行号拆分
     * @param $bomId
     * @return array
     */
    public static function getOrderAndLine($bomId){
        if (!empty(strpos($bomId, '+'))){
            $orderId = strstr($bomId, '+', TRUE);
            $fentryid = substr(strstr($bomId, '+'), 1);
        } else {
            $orderId = $bomId;
            $fentryid = '';
        }
        return [
            'order_id'=>$orderId,
            'fentryid'=>$fentryid
        ];
    }

    /**
     * 获取小车清单
     * @param $bomUuid
     * @return array
     */
    public function getCarList($bomUuid)
    {
        $carSeat = []; //记录物料小车站位信息
        $bomReels = [];//记录装车Bom单的数量信息
        $materiel = []; //返回前端页面显示集合
        $count = -1;
        $finishedQty = [];
        $smtMateriel = [];
        $fileModel = new FileModel();
        $file = $fileModel->findFileByBomUuid($bomUuid);
        if(empty($file)){
            return ret_template(false,'暂无装车文件');
        }
        $filePath = CMF_ROOT.$file;
        if (!file_exists($filePath)) {
            return ret_template(false,'装车文件丢失');
        }
        $carReels = json_decode($filePath->read(), true);
        if (!empty($carReels)) {
            //存在合并Bom单装车情况下，将物料数量信息整合
            foreach ($carReels['bomIds'] as $order) {
                $outPutFile = new CommonFile('', Constant::RECORD_OUTPUT_COUNT . $order . Constant::RECORD_FILE_SUFFIX);
                $bomContent = json_decode($outPutFile->read(), true);
                foreach ($bomContent as $k => $sub_materiel_id) {
                    if (!empty($bomReels[$k])) {
                        $bomReels[$k]['originalCount'] += $sub_materiel_id['originalCount'];
                        $bomReels[$k]['oughtCount'] += $sub_materiel_id['oughtCount'];
                    } else {
                        $bomReels[$k] = $sub_materiel_id;
                    }
                }
            }

            $materielId = array_column($carReels['data'], 'sub_materiel_id');
            //处理小车清单站位显示，将有上车物料站位取出处理。
            //一单多次装车时存在一料一车一簇，一料一车多簇，一料多车多簇
            foreach ($carReels['data'] as $value) {
                $count += 1;
                $key = $value['sub_materiel_id'];
                $carSeat[$key]['plateNumber'] += 1;
                $index = array_search($value['carId'], $carSeat[$key]['carId']);
                if ($index === false || $index === null) {
                    empty($carSeat[$key]['carCode']) ? $carSeat[$key]['carCode'] = [] : '';
                    array_push($carSeat[$key]['carCode'], $value['car_code']);
                    $carSeat[$key]['seatCode'][count($carSeat[$key]['carCode']) - 1][0] = $value['car_seat_code'];
                } else {
                    //如果前后物料相同代表同一种物料连续存放用-连接
                    if ($materielId[$count - 1] == $materielId[$count] && $count != 0) {
                        $k = count($carSeat[$key]['seatCode'][$index]);
                        if ($k == 0 || substr($value['car_seat_code'], 0, 1) == 'C') {
                            $carSeat[$key]['seatCode'][$index][$k - 1] = $value['car_seat_code'];
                        } else {
                            if (empty($carSeat[$key]['seatCode'][$index][$k - 1])) {
                                $carSeat[$key]['seatCode'][$index] = [];
                            } else {
                                array_push($carSeat[$key]['seatCode'][$index], $value['car_seat_code']);
                            }
                        }
                    } else {
                        array_push($carSeat[$key]['seatCode'][$index], $value['car_seat_code']);
                    }
                }
            }

            //对物料的小车站位多维数组转一维数组 同一个物料同车不连续站位用、隔开，不同车通过/隔开
            $temp = [];
            foreach ($carSeat as $k => $value) {
                $temp[$k]['carCode'] = implode('/', $value['carCode']);
                foreach ($value['seatCode'] as $length => $item) {
                    $item = array_unique(array_filter($item));
                    if (is_array($item) && count($item) > 1) {
                        $item = min($item) . '-' . max($item);
                    } else {
                        $item = $item[0];
                    }
                    $temp[$k]['seatCode'] .= $item;
                    if ($length < count($value['seatCode']) - 1) {
                        $temp[$k]['seatCode'] .= '/';
                    }
                }
            }

            //处理小车清单各类数量信息显示及其备注
            $finishedQty = array_unique($finishedQty);

            foreach ($bomReels as $k => $value) {
                $materiel[$k]['sub_materiel_id'] = $k;
                $materiel[$k]['originalCount'] = $value['originalCount'];
                $materiel[$k]['measure'][0] = 0;
                foreach ($finishedQty as $key => $item) {
                    $materiel[$k]['measure'][$key] = sprintf("%d", $value['originalCount'] / $item);
                }
                $materiel[$k]['measure'] = implode('、', $materiel[$k]['measure']);
                $materiel[$k]['oughtCount'] = $value['oughtCount'];
                $materiel[$k]['secondCount'] = empty($secondContent[$k]['oughtCount']) ? '' : $secondContent[$k]['oughtCount'];
                $materiel[$k]['plateNumber'] = empty($carSeat[$k]['plateNumber']) ? 0 : $carSeat[$k]['plateNumber'];
                $materiel[$k]['carCode'] = empty($temp[$k]['carCode']) ? '' : $temp[$k]['carCode'];
                $materiel[$k]['seatCode'] = empty($temp[$k]['seatCode']) ? '' : $temp[$k]['seatCode'];
                if ($value['originalCount'] > $value['oughtCount']) {
                    $smtMateriel[$k] = [
                        'sub_materiel_id' => $k,
                        'count' => $materiel[$k]['originalCount'] - $materiel[$k]['oughtCount']
                    ];
                    $materiel[$k]['remark'] = "应补发({$smtMateriel[$k]['count']})";
                } else if ($value['originalCount'] == 0 && $value['planCount'] == 0 && $value['oughtCount'] == 0) {
                    $materiel[$k]['remark'] = '有替代';
                } else if ($value['originalCount'] != 0 && $value['planCount'] != 0 && $value['planCount'] > $value['oughtCount']) {
                    $materiel[$k]['remark'] = '欠料';
                } else {
                    $materiel[$k]['remark'] = '';
                }
            }
            $materiel = array_values($materiel);
            array_multisort(array_column($materiel, 'sub_materiel_id'), SORT_ASC, $materiel);
            return $materiel;
        }
        return [];
    }

    /**
     * 添加K3订单
     * @param $orderId
     * @param $hidden
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */

    public function addBomFromK3($orderId, $hidden)
    {
        $orderId = strtoupper(str_replace(array(PHP_EOL,"\t"," "), '', $orderId));
        $order = strtolower(str_replace(array(PHP_EOL,"\t"," "), '', $orderId));
        $words = explode(',',AppConstant::BOM_TITLE);
        preg_match('/\w[A-z]+/', $order, $arr);
        if (!in_array($arr[0], $words)) {
            return ret_template(false, '订单格式不正确');
        }
        $type = $arr[0];
        $bomService = new BomService();
        $order = $bomService::getOrderAndLine($order);
        $bomInfo = $this->bomModel->where($order)->find();
        if (count($bomInfo)) {
            $bomInfo = $bomInfo->toArray();
            if ($bomInfo['hidden'] == 1 && $hidden == 0) {
                $hidden = 2;
            }
            $this->bomModel->where($order)->update(['hidden' => $hidden, 'time' => get_current_time()]);
            return ret_template(true, '出库单生成成功');
        }
        $condition = empty($order['fentryid'])?$orderId:$order;
        $bomK3 = K3ReaderFactory::read($type, $condition);
        if (empty($bomK3)) {
            return ret_template(false, 'K3订单数据为空');
        }
        $supplierId = $bomK3[0]['supplier_id'];
        $supplierUuid = '';
        if(!empty($supplierId)){ //新K3直属单内视图内包含着SMT委外单
            $supplier = SupplierService::create_supplier($supplierId);
            $supplierUuid = $supplier['data'][0]['uuid'];
            if ($supplier['success'] == false) {
                return ret_template(false, $supplier['message']);
            }
        }
        $bomUuid = count($bomInfo) ? $bomInfo['uuid'] : create_uuid();
        $bomDetail = [];
//        $remark = '产品:'.$bomK3[0]['fcpnumber'].' 数量:'.$bomK3[0]['fqty'];
        $number = (int)$bomK3[0]['fqty'];//新版本修改
        $remark = '产品:'.$bomK3[0]['fcpnumber'].' 数量:'.$number;
        foreach ($bomK3 as $k => $item) {
            $materielCode = $item['sub_materiel_id'];
            $count = $bomDetail[$materielCode]['count'];
            $bomDetail[$materielCode] = Template::bomDetailTemplate($bomUuid, $materielCode, $item['count'] + $count);
            unset($bomK3[$k]);
        }
        $bomDetail = array_values($bomDetail);
        $bom = Template::bomTemplate($bomUuid, $order['order_id'], $order['fentryid'], '', $supplierUuid, AppConstant::MANUAL_BOM,'', $hidden, '', '', $remark);
        $materielList = array_unique(array_column($bomDetail, 'sub_materiel_id'));
        $materiel = MaterielService::create_materiel($materielList);
        if ($materiel['success'] == false) {
            return ret_template(false, $materiel['message']);
        }

        $bomModel = new BomModel();
        $bomModel->startTrans();
        $tranBom = $bomModel->insert($bom, true);
        $tranDetail = true;
        if (!empty($bomDetail)) {
            $bomDetailModel = new BomDetailModel();
            $tranDetail = $bomDetailModel->insertAll($bomDetail);
        }
        if ($tranBom && $tranDetail) {
            $bomModel->commit();
            $result = ret_template(true, '出库单生成成功');
        } else {
            $bomModel->rollback();
            $result = ret_template(false, '出库单生成异常');
        }
        return $result;
    }

    public function addBomFromExcel()
    {
        $materielBom = ExcelReaderFactory::read('materiel_bom');
        $checkExcel = $materielBom->checkExcelConfig();
        if ($checkExcel['success'] === false) {
            return $checkExcel;
        }
        $checkData = $materielBom->checkData();
        if ($checkData['success'] === false) {
            return $checkData;
        }
        $result = $materielBom->insertToDb();
        return $result;
    }

    public function rePush($bomUuid, $orderId)
    {
        $userModel = new UserModel();
        $storageList = $userModel->getCurrentStaffStorage();                             //获取当前登入账户管理仓库
        empty($storageList) ? $where = [] : $where['uuid'] = ['in', $storageList];
        $storageInfo = Db::table('iwh_storage')->field('uuid,bom_uuid,type')->where($where)->select();//获取管理仓库下目前正在出库的订单
        $storageInfo = empty($storageInfo) ? [] : $storageInfo;
        foreach ($storageInfo as $key=>$item){
            if ($item['bom_uuid'] = $bomUuid){
                $index = $key;
                break;
            }
        }
//        $index = array_search(['bom_uuid'=>$bomUuid], $storageInfo);                                 //判断重推订单所属仓库
        if (empty($storageInfo)) {
            return ret_template(false, '没有出库单正在出库');
        }
        if ($index === false || $index === null) {
            return ret_template(false, '该出库单不是仓储员管理仓库正在出库的订单');
        }
        if ($storageInfo[$index]['type'] === 0) {
            return ret_template(false, '该仓库没有安装灯板不能重推亮灯');
        }
        $storageUuid = $storageInfo[$index]['uuid'];
        $filePath = Constant::RECORD_OUTPUT . $orderId . Constant::RECORD_FILE_SUFFIX;
        $file = new CommonFile($storageUuid, $filePath);
        if (!file_exists($file->getFilePath())) {
            return ret_template(false, '失败，缓存文件不存在');
        }

        $data = json_decode($file->read(), true);
        foreach ($data['performData'] as $item) {
            if (!$item['isFinish']) {
                $seatCode[] = $item['seatCode'];
            }
        }
        foreach ($data['batchData'] as $item) {
            if (!$item['isFinish']) {
                $seatCode[] = $item['seatCode'];
            }
        }

        if (!empty($seatCode)) {
            $where = [
                'storage_uuid' => $storageUuid,
                'seat_code' => ['in', $seatCode]
            ];
            $seatModel = new SeatModel();
            $seatIds = $seatModel->where($where)->column('seat_id');
            $seatIds = array_values(array_filter(array_unique($seatIds)));//去空去重
        }

        if (!empty($seatIds)) {
            SocketService::send($seatIds, $storageUuid, 2);
        }
        return ret_template(true, '重推成功');
    }

    public function balance($bomUuid, $orderId)
    {
        $userModel = new UserModel();
        $storageList = $userModel->getCurrentStaffStorage();                             //获取当前登入账户管理仓库
        empty($storageList) ? $where = [] : $where['uuid'] = ['in', $storageList];
        $storageInfo = Db::table('iwh_storage')->field('uuid,bom_uuid,type')->where($where)->select();//获取管理仓库下目前正在出库的订单
        $storageInfo = empty($storageInfo) ? [] : $storageInfo;
        $storageArray = $storageInfo->toArray();
        if (empty($storageArray[0]['bom_uuid'])) {
            return ret_template(false, '没有出库单正在出库');
        }
        foreach ($storageArray as $key=>$item){
            if ($item['bom_uuid'] = $bomUuid){
                $index = $key;
                break;
            }
        }                               //判断重推订单所属仓库

        if ($index === false || $index === null) {
            return ret_template(false, '该出库单不是仓储员管理仓库正在出库的订单');
        }
        $bomModel = new BomModel();
        $bomInfo = $bomModel->with('Supplier')->where('uuid', $bomUuid)->find();
        if ($bomInfo['supplier_type'] == 0) {
            $handler = new ForeignOutputService();
        } else {
            $handler = new LocalOutputService();
        }
        $res = $handler->complete($orderId, $storageInfo[$index]['uuid']);
        if ($res) {
            $result = ret_template(true, "结算成功");
        } else {
            $result = ret_template(true, "结算失败");
        }
        return $result;
    }

}